//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.1
#include "sdram_bsp.h"
#include <stdio.h>

/*延迟一段时间*/
static inline void SDRAM_delay(volatile unsigned int nCount)
{
    for (volatile unsigned int index = (100000 * nCount); index != 0; index--)
    {
    }
}
/*初始化控制SDRAM的IO*/
static void SDRAM_BSP_GPIO_Init(void)
{
    /*地址信号线*/
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A0_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A1_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A2_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A3_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A4_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A5_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A6_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A7_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A8_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A9_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A10_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_A11_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_BA0_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_BA1_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A0_GPIO_PORT, FMC_A0_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A1_GPIO_PORT, FMC_A1_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A2_GPIO_PORT, FMC_A2_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A3_GPIO_PORT, FMC_A3_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A4_GPIO_PORT, FMC_A4_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A5_GPIO_PORT, FMC_A5_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A6_GPIO_PORT, FMC_A6_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A7_GPIO_PORT, FMC_A7_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A8_GPIO_PORT, FMC_A8_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A9_GPIO_PORT, FMC_A9_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A10_GPIO_PORT, FMC_A10_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_A11_GPIO_PORT, FMC_A11_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_BA0_GPIO_PORT, FMC_BA0_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_BA1_GPIO_PORT, FMC_BA1_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A0_GPIO_PORT, FMC_A0_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A1_GPIO_PORT, FMC_A1_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A2_GPIO_PORT, FMC_A2_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A3_GPIO_PORT, FMC_A3_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A4_GPIO_PORT, FMC_A4_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A5_GPIO_PORT, FMC_A5_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A6_GPIO_PORT, FMC_A6_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A7_GPIO_PORT, FMC_A7_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A8_GPIO_PORT, FMC_A8_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A9_GPIO_PORT, FMC_A9_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A10_GPIO_PORT, FMC_A10_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_A11_GPIO_PORT, FMC_A11_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_BA0_GPIO_PORT, FMC_BA0_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_BA1_GPIO_PORT, FMC_BA1_GPIO_PIN, AFIO_FMC);
    /*数据信号线*/
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D0_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D1_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D2_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D3_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D4_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D5_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D6_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D7_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D8_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D9_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D10_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D11_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D12_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D13_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D14_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_D15_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D0_GPIO_PORT, FMC_D0_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D1_GPIO_PORT, FMC_D1_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D2_GPIO_PORT, FMC_D2_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D3_GPIO_PORT, FMC_D3_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D4_GPIO_PORT, FMC_D4_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D5_GPIO_PORT, FMC_D5_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D6_GPIO_PORT, FMC_D6_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D7_GPIO_PORT, FMC_D7_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D8_GPIO_PORT, FMC_D8_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D9_GPIO_PORT, FMC_D9_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D10_GPIO_PORT, FMC_D10_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D11_GPIO_PORT, FMC_D11_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D12_GPIO_PORT, FMC_D12_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D13_GPIO_PORT, FMC_D13_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D14_GPIO_PORT, FMC_D14_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_D15_GPIO_PORT, FMC_D15_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D0_GPIO_PORT, FMC_D0_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D1_GPIO_PORT, FMC_D1_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D2_GPIO_PORT, FMC_D2_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D3_GPIO_PORT, FMC_D3_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D4_GPIO_PORT, FMC_D4_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D5_GPIO_PORT, FMC_D5_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D6_GPIO_PORT, FMC_D6_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D7_GPIO_PORT, FMC_D7_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D8_GPIO_PORT, FMC_D8_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D9_GPIO_PORT, FMC_D9_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D10_GPIO_PORT, FMC_D10_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D11_GPIO_PORT, FMC_D11_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D12_GPIO_PORT, FMC_D12_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D13_GPIO_PORT, FMC_D13_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D14_GPIO_PORT, FMC_D14_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_D15_GPIO_PORT, FMC_D15_GPIO_PIN, AFIO_FMC);
    /*控制信号线*/
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_CS_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_WE_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_RAS_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_CAS_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_CLK_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_CKE_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_UDQM_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(FMC_LDQM_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_CS_GPIO_PORT, FMC_CS_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_WE_GPIO_PORT, FMC_WE_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_RAS_GPIO_PORT, FMC_RAS_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_CAS_GPIO_PORT, FMC_CAS_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_CLK_GPIO_PORT, FMC_CLK_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_CKE_GPIO_PORT, FMC_CKE_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_UDQM_GPIO_PORT, FMC_UDQM_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(FMC_LDQM_GPIO_PORT, FMC_LDQM_GPIO_PIN, Mode_AF_PP);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_CS_GPIO_PORT, FMC_CS_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_WE_GPIO_PORT, FMC_WE_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_RAS_GPIO_PORT, FMC_RAS_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_CAS_GPIO_PORT, FMC_CAS_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_CLK_GPIO_PORT, FMC_CLK_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_CKE_GPIO_PORT, FMC_CKE_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_UDQM_GPIO_PORT, FMC_UDQM_GPIO_PIN, AFIO_FMC);
    WHT_GPIO_BSP.WHT_Set_AFIO(FMC_LDQM_GPIO_PORT, FMC_LDQM_GPIO_PIN, AFIO_FMC);		
}
/*对SDRAM芯片进行初始化配置*/
static void SDRAM_BSP_Config_Init(void)
{
    FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStruct;
    unsigned int tmpr = 0;
    
    /* Step 3:配置命令：开启提供给SDRAM的时钟 */
    FMC_SDRAMCommandStruct.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
    FMC_SDRAMCommandStruct.FMC_CommandTarget = FMC_COMMAND_TARGET_BANK;
    FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber = 0;
    FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition = 0;
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET)
    {
    }
    /* 发送上述命令*/
    FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
  
    /* Step 4:延时 */
    SDRAM_delay(10);
    
    /* Step 5：配置命令：对所有的bank预充电 */
    FMC_SDRAMCommandStruct.FMC_CommandMode = FMC_Command_Mode_PALL;
    FMC_SDRAMCommandStruct.FMC_CommandTarget = FMC_COMMAND_TARGET_BANK;
    FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber = 0;
    FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition = 0;
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET)
    {
    }
    /* 发送上述命令*/
    FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
  
    /* Step 6：配置命令：自动刷新 */   
    FMC_SDRAMCommandStruct.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
    FMC_SDRAMCommandStruct.FMC_CommandTarget = FMC_COMMAND_TARGET_BANK;
    FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber = 2;			//2个自动刷新命令
    FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition = 0;
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET)
    {
    }
    /* 发送自动刷新命令*/
    FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
    
    /* Step 7：设置sdram寄存器配置 */
    tmpr = SDRAM_MODEREG_BURST_LENGTH_4 | SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
            SDRAM_MODEREG_CAS_LATENCY_2 | SDRAM_MODEREG_OPERATING_MODE_STANDARD |
            SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
    
    /* 配置命令：设置SDRAM寄存器 */
    FMC_SDRAMCommandStruct.FMC_CommandMode = FMC_Command_Mode_LoadMode;
    FMC_SDRAMCommandStruct.FMC_CommandTarget = FMC_COMMAND_TARGET_BANK;
    FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber = 1;
    FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition = tmpr;
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET)
    {
    }
    /* 发送上述命令*/
    FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
  
    /* Step 8：设置刷新计数器 */
	/*刷新速率 = (COUNT + 1) x SDRAM 频率时钟 COUNT =（ SDRAM 刷新周期/行数) - 20*/
    /* 64ms/4096=15.62us  (15.62 us x FSDCLK) - 20 =1386 */
    FMC_SetRefreshCount(1386);
    /* 发送上述命令*/
    while(FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET)
    {
    }
}
/*初始化配置使用SDRAM的FMC及GPIO接口，本函数在SDRAM读写操作前需要被调用*/
static ErrorStatus SDRAM_BSP_Register(void)
{
    FMC_SDRAMInitTypeDef  FMC_SDRAMInitStruct;
    FMC_SDRAMTimingInitTypeDef  FMC_SDRAMTimingStruct; 
    
    /* 配置FMC接口相关的 GPIO*/
    SDRAM_BSP_GPIO_Init();
    
    /* 使能 FMC 时钟 */
    RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);
    
    /* SDRAM时序结构体，根据SDRAM参数表配置----------------*/
    /* SDCLK： 90 Mhz (HCLK/2 :180Mhz/2) 1个时钟周期Tsdclk =1/90MHz=11.11ns*/
    /* TMRD: 2 Clock cycles */
    FMC_SDRAMTimingStruct.FMC_LoadToActiveDelay    = 2;      
    /* TXSR: min=70ns (7x11.11ns) */
    FMC_SDRAMTimingStruct.FMC_ExitSelfRefreshDelay = 7;
    /* TRAS: min=42ns (4x11.11ns) max=120k (ns) */
    FMC_SDRAMTimingStruct.FMC_SelfRefreshTime      = 4;
    /* TRC:  min=70 (7x11.11ns) */        
    FMC_SDRAMTimingStruct.FMC_RowCycleDelay        = 7;         
    /* TWR:  min=1+ 7ns (1+1x11.11ns) */
    FMC_SDRAMTimingStruct.FMC_WriteRecoveryTime    = 2;      
    /* TRP:  15ns => 2x11.11ns */
    FMC_SDRAMTimingStruct.FMC_RPDelay              = 2;                
    /* TRCD: 15ns => 2x11.11ns */
    FMC_SDRAMTimingStruct.FMC_RCDDelay             = 2;

    /* FMC SDRAM 控制配置 */
    /*选择存储区域*/
    FMC_SDRAMInitStruct.FMC_Bank = FMC_BANK_SDRAM;
    /* 行地址线宽度: [7:0] */
    FMC_SDRAMInitStruct.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
    /* 列地址线宽度: [11:0] */
    FMC_SDRAMInitStruct.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
    /* 数据线宽度 */
    FMC_SDRAMInitStruct.FMC_SDMemoryDataWidth = SDRAM_MEMORY_WIDTH; 
    /* SDRAM内部bank数量*/
    FMC_SDRAMInitStruct.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
    /* CAS潜伏期 */
    FMC_SDRAMInitStruct.FMC_CASLatency = SDRAM_CAS_LATENCY; 
    /* 禁止写保护*/
    FMC_SDRAMInitStruct.FMC_WriteProtection = FMC_Write_Protection_Disable;
    /* SDCLK时钟分频因子，SDCLK = HCLK/SDCLOCK_PERIOD*/
    FMC_SDRAMInitStruct.FMC_SDClockPeriod = SDCLOCK_PERIOD; 
    /* 突发读模式设置*/  
    FMC_SDRAMInitStruct.FMC_ReadBurst = SDRAM_READBURST;
    /* 读延迟配置 */
    FMC_SDRAMInitStruct.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_0;
    /* SDRAM时序参数 */
    FMC_SDRAMInitStruct.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingStruct;
    
    /* 调用初始化函数，向寄存器写入配置 */
    FMC_SDRAMInit(&FMC_SDRAMInitStruct); 
    /* 执行FMC SDRAM的初始化流程*/
    SDRAM_BSP_Config_Init();
    return SUCCESS;
}


/*Waiting SDRAM Idle*/
static void SDRAM_BSP_Waiting_Idle(void)
{
    /* 禁止写保护 */
    FMC_SDRAMWriteProtectionConfig(FMC_Bank2_SDRAM, DISABLE);
    /* 检查SDRAM标志，等待至SDRAM空闲 */ 
    while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
    {
    }
}

/*按照1字节写SDRAM*/
static void SDRAM_BSP_Write_1Byte(const unsigned char* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned char* Datax = (unsigned char*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *Datax++ = *buffer++;
    }
}
/*按照1字节读SDRAM*/
static void SDRAM_BSP_Read_1Byte(unsigned char* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned char* Datax = (unsigned char*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *buffer++ = *Datax++;
    }
}

/*按照2字节写SDRAM*/
static void SDRAM_BSP_Write_2Byte(const unsigned short* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned short* Datax = (unsigned short*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *Datax++ = *buffer++;
    }
}
/*按照2字节读SDRAM*/
static void SDRAM_BSP_Read_2Byte(unsigned short* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned short* Datax = (unsigned short*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *buffer++ = *Datax++;
    }
}

/*按照4节写SDRAM*/
static void SDRAM_BSP_Write_4Byte(const unsigned int* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned int* Datax = (unsigned int*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *Datax++ = *buffer++;
    }
}
/*按照4字节读SDRAM*/
static void SDRAM_BSP_Read_4Byte(unsigned int* buffer, unsigned int address, unsigned int length)
{
    volatile unsigned int* Datax = (unsigned int*)(SDRAM_BANK_ADDR + address);

    SDRAM_BSP_Waiting_Idle();
    while(length--)
    {
        *buffer++ = *Datax++;
    }
}

/*使用DMA写SDRAM*/
static void SDRAM_BSP_Write_DMA(const void* buffer, unsigned int address, unsigned int size)
{
    SDRAM_BSP_Waiting_Idle();
    WHT_DMA_BSP_Memcpy((void*)(SDRAM_BANK_ADDR + address), buffer, size);//无法知道传输的状态
}
/*使用DMA读SDRAM*/
static void SDRAM_BSP_Read_DMA(void* buffer, unsigned int address, unsigned int size)
{
    SDRAM_BSP_Waiting_Idle();
    WHT_DMA_BSP_Memcpy(buffer, (void*)(SDRAM_BANK_ADDR + address), size);//无法知道传输的状态
}

const WHT_SDRAM_BSP_t WHT_SDRAM_BSP =
{
    .WHT_Register    = SDRAM_BSP_Register,
    .WHT_Write_1Byte = SDRAM_BSP_Write_1Byte,
    .WHT_Write_2Byte = SDRAM_BSP_Write_2Byte,
    .WHT_Write_4Byte = SDRAM_BSP_Write_4Byte,
    .WHT_Read_1Byte  = SDRAM_BSP_Read_1Byte,
    .WHT_Read_2Byte  = SDRAM_BSP_Read_2Byte,
    .WHT_Read_4Byte  = SDRAM_BSP_Read_4Byte,
    .WHT_Write_DMA   = SDRAM_BSP_Write_DMA,
    .WHT_Read_DMA    = SDRAM_BSP_Read_DMA,
};
